/*
 * Project Name: Fix
 * Brief Description: A Simple Fixed Point C++ Library.
 *
 * Date: 04/05/2010
 * Version: Initial
 */

#ifndef _FIX_
#define _FIX_

//Includes
#include <iostream>
#include <vector>

using std::ostream;
using std::vector;

//Defines
#define DEFAULT_DATASZ 1
#define INT_SZ_BYTES sizeof(int)
#define SHORT_DIV_EXTRA_STEP 2

#ifdef WIN64
#define ELEMENT_SHIFT 32
#define MAX_ELEMENT_POS_VALUE 0x7FFFFFFF
#define ALL_BITS_SET_ELEMENT 0xFFFFFFFF
#define SHIFT_UPPER_MULT 0x100000000
#else
#define ELEMENT_SHIFT 16
#define MAX_ELEMENT_POS_VALUE 0x7FFF
#define ALL_BITS_SET_ELEMENT 0xFFFF
#define SHIFT_UPPER_MULT 0x10000
#endif

//typedefs
typedef __int8  int8;
typedef __int16 int16;
typedef __int32 int32;
typedef __int64 int64;

typedef unsigned __int8  uint8;
typedef unsigned __int16 uint16;
typedef unsigned __int32 uint32;
typedef unsigned __int64 uint64;

//Fix the element size for the fix vector
//The source is being composed on a 32-bit Intel Pentium Processor
//therefore the element size is set to 16-bit.
//Reason for this is Windows does not return an exception when
//Two 32-bit numbers are added and the final result overflows.
#ifdef WIN64
typedef uint32 uelement;
typedef int32  element;
//Unsigned double element
typedef uint64 udelement;
typedef int64  delement;
#else
typedef uint16 uelement;
typedef int16  element;
//Unsigned double element
typedef uint32 udelement;
typedef int32  delement;
#endif

inline void doubleSwap(double &lhs, double &rhs);
void dfttest ();
void ffttest ();

/*Quick Swap: Using the XOR Function*/
inline void ElementSwap( element &lhs, element &rhs) {
	if (&lhs != &rhs) {
		lhs ^= rhs;
		rhs ^= lhs;
		lhs ^= rhs;
	}
}

class fix {

	//private members
private:
	/*
	 * Use Signed Int16 to store the fixed  
	 */
	size_t dataSize_upper;
	size_t dataSize_lower;

	//protected members
protected:

	//public members:
public:
	
	std::vector <uelement> fixed;

	size_t getDataSize_upper() const;
	size_t getDataSize_lower() const;

	//Constructor Declaration

	//Default Constructor
	fix();

	//Constructor with int16
	//fix(const int16);

	//Constructor with double element size, just stores the value before
	//basis point. After the basis point it just stores a zero.
	fix(const delement);

	//Constructor with double element size, stores values before and after
	//the basis point. purposely assigned a lower datatype after the basis point
	fix(const delement, const uelement);

	//Constructor with double initialization
	explicit fix(const double);

	//Copy Constructor
	fix(const fix&);

	//Default Destructor
	~fix();

	//Assignment Operator
	const fix& operator= (const fix&);

	// ----- Friend Functions START ----- //
	//Defined outside the Class fix
	//in order to make the class as nimble as possible.
	//Stream Extraction operator
	friend ostream &operator << (ostream &, const fix&);

	//1. Addition Operators
	//a. Add 2 fix's
	friend fix operator + (const fix&, const fix&);

	//b. Add a fix and a integer
	friend fix operator + (const fix&, const delement&);

	//1.ab helper Function
	friend void AddCarryHandle(fix&, element, element);
	//friend void AddCarryHandle(fix&, element, element, element);

	//2. Negation Operator
	friend fix operator - (const fix&);

	//3. Subtraction Operator
	friend fix operator - (const fix&, const fix&);

	//4. Multiplication Operators
	//a. Multiply a fix and an element
	friend fix operator * (const fix&, const element&);

	//b. Multiply a fix and fix!
	friend fix operator * (const fix&, const fix&);

	//5. Division Operators
	//a. Divide a fix and an element
	friend fix operator / (const fix&, const element&);
};


#endif